home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / dev / src / wangisrc.lha / wangi / z / Umentiler / source / Umentiler.c < prev    next >
C/C++ Source or Header  |  1996-01-28  |  25KB  |  1,073 lines

  1. /*************************************************************************
  2.  *
  3.  * Umentiler
  4.  *
  5.  * Copyright ©1995 Lee Kindness cs2lk@scms.rgu.ac.uk
  6.  *
  7.  * Read Umentiler.guide (from the main archive) for distribution details.
  8.  *
  9.  * Umentiler.c
  10.  */
  11.  
  12. /* Includes are kept in gst.c for gst compilation purposes */
  13. #include "gst.c"
  14.  
  15. #ifdef _DCC
  16. #define REG(x)    __ ## x
  17. #define ASM
  18. #define ARGS __regargs
  19. #else
  20. #ifdef __GNUC__
  21. #define REG(x)
  22. #define ASM
  23. #else /* __SASC__ */
  24. #define REG(x)    register __ ## x
  25. #define ASM    __asm
  26. #endif /* __GNUC__ */
  27. #endif /* _DCC */
  28.  
  29. extern struct ExecBase *SysBase;
  30. extern struct DosLibrary *DOSBase;
  31. extern struct LocaleBase *LocaleBase;
  32.  
  33. /* Revision information */
  34. #include "Umentiler_rev.h"
  35.  
  36. /* Version String */
  37. const char ver[] = VERSTAG;
  38.  
  39. /* Example for the documentation ;) */
  40. const char tst[] = "$MOOD: Here is a short story:\n" \
  41.                    "This is the start.\n" \
  42.                    "This is the middle.\n" \
  43.                    "And this is the end!";
  44.  
  45. /*
  46.  * Keep all 'global' vars in a locally allocated and 
  47.  * passed around structure => Gives pure, reentrant code
  48.  * (We get this with SAS anway...)
  49.  */
  50. struct Vars
  51. {
  52.     ULONG              v_Tags_p;
  53.     ULONG              v_Tags_e;
  54.     ULONG              v_Tags_i;
  55.     ULONG              v_BufSize;
  56.     struct Locale     *v_Locale;
  57.     struct LocaleBase *v_LocaleBase;
  58. };
  59.  
  60. /* Prototypes */
  61. STRPTR    strsistr      (STRPTR, STRPTR);
  62. VOID      AddC2Cmd      (STRPTR, char);
  63. VOID      MFPutC        (BPTR, char, BOOL);
  64. VOID      RepMarkers    (struct Vars *, STRPTR, BPTR, BOOL);
  65. VOID      HInsertion    (struct Vars *, BPTR, STRPTR, ULONG);
  66. VOID      HInsertCmd    (struct Vars *, BPTR, STRPTR);
  67. ULONG ASM LFFunc        (REG(a0) struct Hook *,
  68.                          REG(a2) struct Locale *,
  69.                          REG(a1) char);
  70. VOID      HDateCmd      (struct Vars *, BPTR, STRPTR, STRPTR, 
  71.                          LONG, BOOL, BOOL, BOOL);
  72. VOID      HVersionCmd   (struct Vars *, BPTR, STRPTR, BOOL, BOOL, 
  73.                          BOOL, BOOL, BOOL, BOOL);
  74. VOID      HProgramCmd   (struct Vars *, BPTR, STRPTR, BOOL);
  75. VOID      HVarCmd       (BPTR, STRPTR, BOOL, BOOL, BOOL);
  76. VOID      HSetvarCmd    (STRPTR, STRPTR);
  77. VOID      HTagCmd       (struct Vars *, BPTR, STRPTR, STRPTR, BOOL, BOOL);
  78.  
  79.  
  80. /* Template for all temp file names */
  81. #define TMP_TEMP "T:UXXXXXX.XXX"
  82.  
  83.  
  84. /*************************************************************************
  85.  * strsistr() - returns s if f occurs at the start of s. Case insensitive.
  86.  */
  87.  
  88. STRPTR strsistr(STRPTR s, STRPTR f)
  89. {
  90.     if( s && f )
  91.     {
  92.         BOOL match = TRUE;
  93.         for( ; *s && *f && match; ++s, ++f )
  94.             if( toupper(*s) != toupper(*f) )
  95.                 match = FALSE;
  96.         if( match )
  97.             return( s );
  98.         else
  99.             return( NULL );
  100.     } else
  101.         return( NULL ); 
  102. }
  103.  
  104.  
  105. /*************************************************************************
  106.  * AddC2Cmd() - Add a charcter to the command string
  107.  */
  108.  
  109. VOID AddC2Cmd(STRPTR cmd, char ch)
  110. {
  111.     STRPTR s;
  112.     /* Find the null */
  113.     s = strchr(cmd, '\0');
  114.     /* Add the char */
  115.     *s = ch;
  116.     /*
  117.      * ++s;
  118.      * *s = '\0'
  119.      *
  120.      * (no need, we MEMF_CLEARed it)
  121.      */
  122. }
  123.  
  124.  
  125. /*************************************************************************
  126.  * MFPutC() - Will FPutC if certain conditions.
  127.  */
  128.  
  129. VOID MFPutC(BPTR file, char ch, BOOL nolines)
  130. {
  131.     if( !(nolines && ch == '\n') )
  132.         FPutC(file, ch);
  133. }
  134.  
  135.  
  136. /*************************************************************************
  137.  * HInsertion() - Insert text into the file
  138.  */
  139.  
  140. /* Commands */
  141. #define TXT_INSERT "INSERT"
  142. #define CMD_INSERT 1
  143. #define TXT_DATE "DATE"
  144. #define CMD_DATE 2
  145. #define TXT_VERSION "VERSION"
  146. #define CMD_VERSION 3
  147. #define TXT_PROGRAM "PROGRAM"
  148. #define CMD_PROGRAM 4
  149. #define TXT_VAR "VAR"
  150. #define CMD_VAR 5
  151. #define TXT_SETVAR "SETVAR"
  152. #define CMD_SETVAR 6
  153. #define TXT_TAG "TAG"
  154. #define CMD_TAG 7
  155.  
  156. /* And ReadArg() templates for each */
  157. #define TMP_INSERT "FILE/A"
  158. #define OPT_INSERT_FILE 0
  159. #define TMP_DATE "FROM/K,LF=LOCALEFORMAT/K,F=FORMAT/N/K,NY=NODAY/S,ND=NODATE/S,NT=NOTIME/S"
  160. #define OPT_DATE_FROM 0
  161. #define OPT_DATE_LOCALEFORMAT 1
  162. #define OPT_DATE_FORMAT 2
  163. #define OPT_DATE_NODAY 3
  164. #define OPT_DATE_NODATE 4
  165. #define OPT_DATE_NOTIME 5
  166. #define TMP_VERSION "FROM/A,F=FULL/S,NN=NONAME/S,NV=NOVER/S,ND=NODATE/S,NPD=NOPARSEDATE/S,USETAG/S"
  167. #define OPT_VERSION_FROM 0
  168. #define OPT_VERSION_FULL 1
  169. #define OPT_VERSION_NONAME 2
  170. #define OPT_VERSION_NOVER 3
  171. #define OPT_VERSION_NODATE 4
  172. #define OPT_VERSION_NOPARSEDATE 5
  173. #define OPT_VERSION_USETAG 6
  174. #define TMP_PROGRAM "NL=NOLINES/S,CMDLINE/A/F"
  175. #define OPT_PROGRAM_NOLINES 0
  176. #define OPT_PROGRAM_CMDLINE 1
  177. #define TMP_VAR "FROM/A,NL=NEWLINE/S,G=GLOBAL/S,L=LOCAL/S"
  178. #define OPT_VAR_FROM 0
  179. #define OPT_VAR_NEWLINE 1
  180. #define OPT_VAR_GLOBAL 2
  181. #define OPT_VAR_LOCAL 3
  182. #define TMP_SETVAR "NAME/A,TEXT/A/F"
  183. #define OPT_SETVAR_NAME 0
  184. #define OPT_SETVAR_TEXT 1
  185. #define TMP_TAG "TAG/A,FILE/A,NONLCUT/S,DOLLERCUT/S"
  186. #define OPT_TAG_TAG 0
  187. #define OPT_TAG_NAME 1
  188. #define OPT_TAG_NONLCUT 2
  189. #define OPT_TAG_DOLLERCUT 3
  190.  
  191. /* Maximum number of options */
  192. #define OPT_ALL_MAX (OPT_VERSION_USETAG + 1)
  193. #define NOARG "\n"
  194.  
  195. VOID HInsertion(struct Vars *vars, BPTR destf, STRPTR cmd, ULONG cmdsize)
  196. {
  197.     STRPTR s, arg, temp;
  198.     LONG cnum;
  199.     
  200.     /* Skip any initial white space */
  201.     cmd = stpblk(cmd);
  202.     
  203.     /* skip to the arguments */
  204.     if( arg = strpbrk(cmd, "\t ") )
  205.         arg = stpblk(arg);
  206.     else
  207.         arg = NOARG;
  208.     
  209.     /* What command ? */
  210.     if( s = strsistr(cmd, TXT_INSERT) )
  211.     {
  212.         cnum = CMD_INSERT;
  213.         temp = TMP_INSERT;
  214.     } else if( s = strsistr(cmd, TXT_DATE) )
  215.     {
  216.         cnum = CMD_DATE;
  217.         temp = TMP_DATE;
  218.     } else if( s = strsistr(cmd, TXT_VERSION) )
  219.     {
  220.         cnum = CMD_VERSION;
  221.         temp = TMP_VERSION;
  222.     } else if( s = strsistr(cmd, TXT_PROGRAM) )
  223.     {
  224.         cnum = CMD_PROGRAM;
  225.         temp = TMP_PROGRAM;
  226.     } else if( s = strsistr(cmd, TXT_VAR) )
  227.     {
  228.         cnum = CMD_VAR;
  229.         temp = TMP_VAR;
  230.     } else if( s = strsistr(cmd, TXT_SETVAR) )
  231.     {
  232.         cnum = CMD_SETVAR;
  233.         temp = TMP_SETVAR;
  234.     } else if( s = strsistr(cmd, TXT_TAG) )
  235.     {
  236.         cnum = CMD_TAG;
  237.         temp = TMP_TAG;
  238.     } else
  239.     {
  240.         PrintFault(ERROR_ACTION_NOT_KNOWN, cmd);
  241.         cnum = 0;
  242.         temp = NULL;
  243.         ++vars->v_Tags_i;
  244.     }
  245.     if( cnum && temp && arg )
  246.     {
  247.         struct RDArgs *rda;
  248.         
  249.         /* Add a newline to the end of cmd (for ReadArgs()) */
  250.         if( *cmd != '\n' )
  251.             AddC2Cmd(cmd, '\n');
  252.         
  253.         if( rda = AllocDosObject(DOS_RDARGS, NULL) )
  254.         {
  255.             STRPTR args[OPT_ALL_MAX];
  256.             
  257.             rda->RDA_DAList = NULL;
  258.             rda->RDA_Flags |= RDAF_NOPROMPT;
  259.             rda->RDA_Buffer = NULL;
  260.             rda->RDA_Source.CS_Buffer = arg;
  261.             rda->RDA_Source.CS_Length = strlen(arg);
  262.             rda->RDA_Source.CS_CurChr = 0;
  263.             
  264.             memset(&args, 0, (sizeof(STRPTR) * OPT_ALL_MAX));
  265.             
  266.             /* Parse argumesnts for the option */
  267.             if( ReadArgs(temp, (LONG *)&args, rda) ) 
  268.             {
  269.                 switch( cnum )
  270.                 {
  271.                     case CMD_INSERT :
  272.                         HInsertCmd(vars, destf, args[OPT_INSERT_FILE]);
  273.                         break;
  274.                         
  275.                     case CMD_VERSION :
  276.                         HVersionCmd(vars, destf, args[OPT_VERSION_FROM],
  277.                                      (BOOL)args[OPT_VERSION_FULL],
  278.                                      (BOOL)args[OPT_VERSION_NONAME],
  279.                                      (BOOL)args[OPT_VERSION_NOVER],
  280.                                      (BOOL)args[OPT_VERSION_NODATE],
  281.                                      (BOOL)args[OPT_VERSION_NOPARSEDATE],
  282.                                      (BOOL)args[OPT_VERSION_USETAG]);
  283.                         break;
  284.                         
  285.                     case CMD_PROGRAM :
  286.                         HProgramCmd(vars, destf, args[OPT_PROGRAM_CMDLINE],
  287.                                            (BOOL)args[OPT_PROGRAM_NOLINES]);
  288.                         break;
  289.                         
  290.                     case CMD_DATE :    
  291.                         HDateCmd(vars, destf, args[OPT_DATE_FROM],
  292.                                               args[OPT_DATE_LOCALEFORMAT],
  293.                                               args[OPT_DATE_FORMAT] ? *((LONG *)args[OPT_DATE_FORMAT]) : 0,
  294.                                         (BOOL)args[OPT_DATE_NODAY],
  295.                                         (BOOL)args[OPT_DATE_NODATE],
  296.                                         (BOOL)args[OPT_DATE_NOTIME]);
  297.                         break;
  298.                     
  299.                     case CMD_VAR :
  300.                         HVarCmd(destf, args[OPT_VAR_FROM],
  301.                                  (BOOL)args[OPT_VAR_NEWLINE],
  302.                                  (BOOL)args[OPT_VAR_GLOBAL],
  303.                                  (BOOL)args[OPT_VAR_LOCAL]);
  304.                         break;
  305.                     
  306.                     case CMD_SETVAR :
  307.                         HSetvarCmd(args[OPT_SETVAR_NAME],
  308.                                    args[OPT_SETVAR_TEXT]);
  309.                         break;
  310.                     
  311.                     case CMD_TAG :
  312.                         HTagCmd(vars, destf, args[OPT_TAG_TAG],
  313.                                 args[OPT_TAG_NAME],
  314.                           (BOOL)args[OPT_TAG_NONLCUT],
  315.                           (BOOL)args[OPT_TAG_DOLLERCUT]);
  316.                         break;
  317.                 }
  318.                 ++vars->v_Tags_p;
  319.                 FreeArgs(rda);
  320.             } else
  321.                 ++vars->v_Tags_i;
  322.             FreeDosObject(DOS_RDARGS, rda);
  323.         }
  324.     }
  325.     /* Clear cmd */
  326.     memset(cmd, 0, cmdsize);
  327. }
  328.  
  329.  
  330. /*************************************************************************
  331.  * HInsertCmd() - Handle the INSERT command.
  332.  */
  333.  
  334. VOID HInsertCmd(struct Vars *vars, BPTR destf, STRPTR from)
  335. {
  336.     /* paste a file
  337.      * We simply recurse, call RepMarkers()
  338.      */
  339.     RepMarkers(vars, from, destf, FALSE);
  340. }
  341.  
  342.  
  343. /*************************************************************************
  344.  * HVersionCmd() - Handle the VERSION command.
  345.  */
  346.  
  347. #define VERSION_CMD_1ST_PART "Version "
  348. #define VERSION_CMD_2ND_PART " FULL"
  349. #define VERBUF_SIZE 256
  350. #define STATE_NAME 0
  351. #define STATE_VERSION 1
  352. #define STATE_DATE 2
  353.  
  354. VOID HVersionCmd(struct Vars *vars, BPTR destf, STRPTR from, 
  355.                  BOOL full, BOOL noname, BOOL nover, 
  356.                  BOOL nodate, BOOL noparsedate, BOOL usetag)
  357. {
  358.     STRPTR tmpname;
  359.     
  360.     /* Alloc tmpname */
  361.     if( tmpname = AllocVec(14, 0) )
  362.     {
  363.         strcpy(tmpname, TMP_TEMP);
  364.         mktemp(tmpname);
  365.         if( *tmpname != 0 )
  366.         {
  367.             BPTR tf;
  368.             
  369.             /* Open temp file */
  370.             if( tf = Open(tmpname, MODE_NEWFILE) )
  371.             {
  372.                 /* Change buffer */
  373.                 SetVBuf(tf, NULL, vars->v_BufSize, BUF_FULL);
  374.                 
  375.                 /* Temp file is opened ok, do we use the version command or use
  376.                  * use our internal TAG command?
  377.                  */
  378.                 
  379.                 if( usetag )
  380.                 {
  381.                     HTagCmd(vars, tf, "VER", from, FALSE, FALSE);
  382.                 } else
  383.                 {
  384.                     STRPTR cmd;
  385.     
  386.                     /* Alloc cmd */
  387.                     if( cmd = AllocVec(strlen(VERSION_CMD_1ST_PART) +
  388.                                        strlen(VERSION_CMD_2ND_PART) +
  389.                                        strlen(from) + 1, 0) )
  390.                     {
  391.                         BPTR inf;
  392.                         
  393.                         /* build the command line */
  394.                         strcpy(cmd, VERSION_CMD_1ST_PART);
  395.                         strcat(cmd, from);
  396.                         strcat(cmd, VERSION_CMD_2ND_PART);
  397.                     
  398.                         /* Open input file */
  399.                         if( inf = Open("NIL:", MODE_OLDFILE) )
  400.                         {
  401.                             if( SystemTags(cmd, SYS_Input,  inf,
  402.                                                 SYS_Output, tf,
  403.                                                 TAG_DONE) != 0 )
  404.                             {
  405.                                 PrintFault(IoErr(), from);
  406.                                 Close(tf);
  407.                                 tf = 0;
  408.                             }
  409.                             Close(inf);
  410.                         }
  411.                         FreeVec(cmd);
  412.                     }
  413.                 }
  414.                 
  415.                 if( tf )
  416.                 {
  417.                     STRPTR verbuf;
  418.                             
  419.                     /* Version command successful, alloc verbuf */
  420.                     if( verbuf = AllocVec(VERBUF_SIZE, 0) )
  421.                     {
  422.                         /* Seek to start */
  423.                         Seek(tf, 0, OFFSET_BEGINNING);
  424.                                 
  425.                         /* Read first line */
  426.                         if( FGets(tf, verbuf, VERBUF_SIZE-1) )
  427.                         {
  428.                             STRPTR s;
  429.                             LONG state = STATE_NAME;
  430.                                     
  431.                             /* Remove trailing EOL */
  432.                             if( s = strchr(verbuf, '\n') )
  433.                                 *s = '\0';
  434.                                     
  435.                             if( !full )
  436.                             {
  437.                                 for( s = verbuf; *s ; ++s )
  438.                                 {
  439.                                     switch( state )
  440.                                     {
  441.                                         case STATE_NAME :
  442.                                             if( isspace(*s) )
  443.                                             {
  444.                                                 state++;
  445.                                                 if( (!noname && !nover) ||
  446.                                                           (!noname && nover && !nodate) )
  447.                                                     FPutC(destf, ' ');
  448.                                                 s = stpblk(s);
  449.                                                 --s;
  450.                                             } else
  451.                                             {
  452.                                                 if( !noname )
  453.                                                     FPutC(destf, *s);
  454.                                             }
  455.                                             break;
  456.                                                 
  457.                                         case STATE_VERSION :
  458.                                             if( isspace(*s) )
  459.                                             {
  460.                                                 state++;
  461.                                                 if( !nover && !nodate )
  462.                                                     FPutC(destf, ' ');
  463.                                                 s = stpblk(s);
  464.                                                 --s;
  465.                                             } else
  466.                                             {
  467.                                                 if( !nover )
  468.                                                     FPutC(destf, *s);
  469.                                             }
  470.                                             break;
  471.                                         
  472.                                         case STATE_DATE :
  473.                                             if( !nodate )
  474.                                             {
  475.                                                 if( noparsedate )
  476.                                                     FPutC(destf, *s);
  477.                                                 else
  478.                                                     if( (*s != '(') && (*s != ')') )
  479.                                                         FPutC(destf, *s);
  480.                                             }
  481.                                             break;
  482.                                     }
  483.                                 }
  484.                             } else
  485.                                 FPuts(destf, verbuf);
  486.                         }
  487.                         FreeVec(verbuf);
  488.                     }
  489.                 }
  490.                 Close(tf);
  491.                 DeleteFile(tmpname);
  492.             }
  493.         }
  494.         FreeVec(tmpname);
  495.     }
  496. }
  497.  
  498.  
  499. /*************************************************************************
  500.  * HProgramCmd() - Handle the PROGRAM command.
  501.  */
  502.  
  503.  
  504. VOID HProgramCmd(struct Vars *vars, BPTR destf, STRPTR cmdline, BOOL noline)
  505. {
  506.     STRPTR tmpname;
  507.     
  508.     /* Alloc tmpname */
  509.     if( tmpname = AllocVec(14, 0) )
  510.     {
  511.         strcpy(tmpname, TMP_TEMP);
  512.         mktemp(tmpname);
  513.         if( *tmpname != 0 )
  514.         {
  515.             BPTR tf;
  516.                 
  517.             /* Open temp file */
  518.             if( tf = Open(tmpname, MODE_NEWFILE) )
  519.             {
  520.                 
  521.                 if( SystemTags(cmdline, SYS_Output, tf, TAG_END) == 0 )
  522.                 {
  523.                     Close(tf);
  524.                     tf = 0;
  525.                     /* Recurse */
  526.                     RepMarkers(vars, tmpname, destf, noline);
  527.                 } else
  528.                     PrintFault(IoErr(), cmdline);
  529.  
  530.                 if( tf )
  531.                     Close(tf);
  532.                 DeleteFile(tmpname);
  533.             }
  534.         }
  535.         FreeVec(tmpname);
  536.     }
  537. }
  538.  
  539.  
  540. /*************************************************************************
  541.  * LFFunc() - Hook function for use in HDateCmd() by FormatDate().
  542.  */
  543.  
  544. /* 
  545.  * NOTE: no __saveds keyword, we dont need it and it would make us unpure
  546.  */
  547. ULONG ASM LFFunc(REG(a0) struct Hook *hook,
  548.                  REG(a2) struct Locale *locale,
  549.                  REG(a1) char ch)
  550. {
  551.     /* hook->h_Data contains a BPTR of the file to output to */
  552.     if( ch )
  553.         FPutC((BPTR)hook->h_Data, ch);
  554.     return( TRUE );
  555. }
  556.  
  557.  
  558. /*************************************************************************
  559.  * HDateCmd() - Handle the DATE command.
  560.  */
  561.  
  562. VOID HDateCmd(struct Vars *vars, BPTR destf, STRPTR from, STRPTR localeformat, LONG format, 
  563.               BOOL noday, BOOL nodate, BOOL notime)
  564. {
  565.     struct DateStamp *ds = NULL;
  566.     
  567.     /* Get the datestamp */
  568.     if( from )
  569.     {
  570.         BPTR l;
  571.         
  572.         /* Read it from a file */
  573.         if( l = Lock(from, ACCESS_READ) )
  574.         {
  575.             struct FileInfoBlock *fib;
  576.             
  577.             /* Alloc fib */
  578.             if( fib = AllocDosObject(DOS_FIB, NULL) )
  579.             {
  580.                 if( Examine(l, fib) )
  581.                 {
  582.                     if( ds = AllocVec(sizeof(struct DateStamp), 0) )
  583.                     {
  584.                         /* Copy ds from the fib */
  585.                         memcpy(ds, &fib->fib_Date, sizeof(struct DateStamp));
  586.                     }
  587.                 }
  588.                 FreeDosObject(DOS_FIB, fib);
  589.             }
  590.             UnLock(l);
  591.         } else
  592.             PrintFault(IoErr(), from);
  593.     } else
  594.     {
  595.         if( ds = AllocVec(sizeof(struct DateStamp), 0) )
  596.             ds = DateStamp(ds);
  597.     }
  598.     if( ds )
  599.     {
  600.         /* Are we going to be locale or dos function based? */
  601.         if( localeformat && vars->v_Locale )
  602.         {
  603.             struct Hook *LFHook;
  604.             
  605.             if( LFHook = AllocVec(sizeof(struct Hook), MEMF_CLEAR) )
  606.             {
  607.                 LFHook->h_Entry    = (HOOKFUNC)LFFunc;
  608.                 
  609.                 /* Pass the file handle */
  610.                 LFHook->h_Data = (APTR)destf;
  611.                 
  612.                 FormatDate(vars->v_Locale, localeformat, ds, LFHook);
  613.                 FreeVec(LFHook);
  614.             }
  615.         } else
  616.         {
  617.             unsigned char daystr[LEN_DATSTRING], datestr[LEN_DATSTRING], timestr[LEN_DATSTRING];
  618.             struct DateTime *dt;
  619.             
  620.             if( dt = AllocVec(sizeof(struct DateTime), MEMF_CLEAR) )
  621.             {
  622.                 memcpy(&dt->dat_Stamp, ds, sizeof(struct DateStamp));
  623.                 dt->dat_Format = format;
  624.                 dt->dat_StrDay = (STRPTR)&daystr;
  625.                 dt->dat_StrDate = (STRPTR)&datestr;
  626.                 dt->dat_StrTime = (STRPTR)×tr;
  627.                 if( DateToStr(dt) )
  628.                 {
  629.                     if( !noday )
  630.                     {
  631.                         FPuts(destf, dt->dat_StrDay);
  632.                         if( !nodate || (nodate && !notime) )
  633.                             FPutC(destf, ' ');
  634.                     }
  635.                     
  636.                     if( !nodate )
  637.                     {
  638.                         FPuts(destf, dt->dat_StrDate);
  639.                         if( !notime )
  640.                             FPutC(destf, ' ');
  641.                     }
  642.                     
  643.                     if( !notime )
  644.                         FPuts(destf, dt->dat_StrTime);    
  645.                 }
  646.                 FreeVec(dt);
  647.             }
  648.         }
  649.         FreeVec(ds);
  650.     }
  651. }
  652.  
  653.  
  654. /*************************************************************************
  655.  * HVarCmd() - Handle the VAR command.
  656.  */
  657.  
  658. #define VAR_BUFFER_SIZE 512
  659.  
  660. VOID HVarCmd(BPTR destf, STRPTR from, BOOL newline, BOOL global, BOOL local)
  661. {
  662.     STRPTR buffer;
  663.     
  664.     /* Alloc buffer */
  665.     if( buffer = AllocVec(VAR_BUFFER_SIZE, 0) )
  666.     {
  667.         ULONG flags = LV_VAR;
  668.         
  669.         if( global )
  670.             flags |= GVF_GLOBAL_ONLY;
  671.         else if( local )
  672.             flags |= GVF_LOCAL_ONLY;
  673.         
  674.         if( GetVar(from, buffer, VAR_BUFFER_SIZE, flags) != -1 )
  675.         {
  676.             FPuts(destf, buffer);
  677.             if( newline )
  678.                 FPutC(destf, '\n');
  679.         } else
  680.             PrintFault(IoErr(), from);
  681.         FreeVec(buffer);
  682.     }
  683. }
  684.  
  685.  
  686. /*************************************************************************
  687.  * HSetvarCmd() - Handle the SETVAR command.
  688.  */
  689.  
  690. VOID HSetvarCmd(STRPTR name, STRPTR text)
  691. {
  692.     SetVar(name, text, -1, LV_VAR | GVF_LOCAL_ONLY);
  693. }
  694.  
  695. /*************************************************************************
  696.  * HTagCmd() - Handle the TAG command.
  697.  */
  698.  
  699. #define TAGBUF_SIZE 4096
  700.  
  701. VOID HTagCmd(struct Vars *vars, BPTR destf, STRPTR tag, STRPTR from,
  702.              BOOL nonlcut, BOOL dollercut)
  703. {
  704.     STRPTR stag;
  705.     
  706.     if( (tag) &&
  707.         (stag = AllocVec(strlen(tag)+4, MEMF_CLEAR)) )
  708.     {
  709.         BPTR f;
  710.         
  711.         strcpy(stag, "$: ");
  712.         strins(++stag, tag);
  713.         --stag;
  714.         
  715.         /* Open the source file */
  716.         if( f = Open(from, MODE_OLDFILE) )
  717.         {
  718.             LONG i, ch;
  719.             BOOL found = FALSE;
  720.             
  721.             /* Change buffer */
  722.             SetVBuf(f, NULL, vars->v_BufSize, BUF_FULL);
  723.             
  724.             for( ch = FGetC(f), i = 0; (ch != -1) && (!found); ch = FGetC(f) )
  725.                 if( ch == stag[i] )
  726.                     if( stag[i+1] == 0 )
  727.                         found = TRUE;
  728.                     else
  729.                         ++i;
  730.                 else
  731.                     i = 0;
  732.                     
  733.             if( found )
  734.                 for( ;
  735.                      (ch != -1) &&
  736.                      (ch != '\0') &&
  737.                      ((ch != '$') || !dollercut) &&
  738.                      (((ch != '\r') && (ch != '\n')) || nonlcut);
  739.                      ch = FGetC(f)
  740.                    )
  741.                     if( ch != '\r' )
  742.                         FPutC(destf, ch);
  743.             
  744.             Close(f);
  745.         }
  746.         FreeVec(stag);
  747.     }
  748. }
  749.  
  750.  
  751. /*************************************************************************
  752.  * RepMarkers() - Parse a file and replace 'stuff'
  753.  */
  754.  
  755. /* Command introducors and terminators */
  756. #define INTRODUCER_1 '/'
  757. #define INTRODUCER_2 '>'  /* INTRODUCER = "/>" */
  758. #define TERMINATOR_1 '<'
  759. #define TERMINATOR_2 '\\' /* TERMINATOR = "<\" */
  760. #define ESCAPE_CHAR  '!'
  761.  
  762. /* When read thru a line char by char we can by in any of these states */
  763. #define LEV_ESCAPED_2 -2
  764. #define LEV_ESCAPED_1 -1
  765. #define LEV_NONE 0
  766. #define LEV_1 1
  767. #define LEV_2 2
  768. #define LEV_3 3
  769.  
  770. #define BUFFER_SIZE 256
  771.  
  772. #define CMD_BUF_SIZE strlen(buffer)+2
  773.  
  774. VOID RepMarkers(struct Vars *vars, STRPTR source, BPTR destf, BOOL nolines)
  775. {
  776.     BPTR sourcef;
  777.     
  778.     /* Open source file */
  779.     if( sourcef = Open(source, MODE_OLDFILE) )
  780.     {
  781.         APTR buf;
  782.         
  783.         /* Change buffer */
  784.         SetVBuf(sourcef, NULL, vars->v_BufSize, BUF_FULL); 
  785.  
  786.             
  787.         /* Alloc buf */
  788.         if( buf = AllocVec(BUFFER_SIZE, 0) )
  789.         {
  790.             APTR buffer;
  791.             
  792.             /* Go thru the source file, line by line */
  793.             while( buffer = FGets(sourcef, buf, BUFFER_SIZE-1) )
  794.             {
  795.                 STRPTR cmd;
  796.                 
  797.                 /* Alloc cmd buffer.
  798.                  * strlen(buffer)+2, 1 extra for the null and 1 more cause we add
  799.                  * on a '\n' in HInsertion()
  800.                  */
  801.                 if( cmd = AllocVec(CMD_BUF_SIZE, MEMF_CLEAR) )
  802.                 {
  803.                     register STRPTR s;
  804.                     register LONG level = LEV_NONE;
  805.                     /*
  806.                      * For each line we parse each character in a
  807.                      * state machine manner.
  808.                      */
  809.                     for( s = buffer; *s ; ++s )
  810.                     {
  811.                         switch( level )
  812.                         {
  813.                             case LEV_ESCAPED_1 :
  814.                                 switch( *s )
  815.                                 {
  816.                                     case INTRODUCER_1 :
  817.                                         level = LEV_ESCAPED_2;
  818.                                         break;
  819.                                     
  820.                                     case ESCAPE_CHAR :
  821.                                         level = LEV_ESCAPED_1;
  822.                                         FPutC(destf, (LONG)ESCAPE_CHAR);
  823.                                         break;
  824.                                     
  825.                                     default:
  826.                                         level = LEV_NONE;
  827.                                         FPutC(destf, (LONG)ESCAPE_CHAR);
  828.                                         MFPutC(destf, (LONG)*s, nolines);
  829.                                         break;
  830.                                 }
  831.                                 break;
  832.                                                             
  833.                             case LEV_ESCAPED_2 :
  834.                                 if( *s == INTRODUCER_2 )
  835.                                 {
  836.                                     FPutC(destf, (LONG)INTRODUCER_1);
  837.                                     FPutC(destf, (LONG)INTRODUCER_2);
  838.                                     ++vars->v_Tags_e;
  839.                                 } else
  840.                                 {
  841.                                     FPutC(destf, (LONG)ESCAPE_CHAR);
  842.                                     FPutC(destf, (LONG)INTRODUCER_1);
  843.                                     MFPutC(destf, (LONG)*s, nolines);
  844.                                 }
  845.                                 level = LEV_NONE;
  846.                                 break;
  847.                                 
  848.                             case LEV_NONE :
  849.                                 switch( *s )
  850.                                 {
  851.                                     case INTRODUCER_1 :
  852.                                         level = LEV_1;
  853.                                         break;
  854.                                     case ESCAPE_CHAR :
  855.                                         level = LEV_ESCAPED_1;
  856.                                         break;
  857.                                     default :
  858.                                         level = LEV_NONE;
  859.                                         MFPutC(destf, (LONG)*s, nolines);
  860.                                         break;
  861.                                 }
  862.                                 break;
  863.                                 
  864.                             case LEV_1 :
  865.                                 if( *s == INTRODUCER_2 )
  866.                                     level = LEV_2;
  867.                                 else
  868.                                 {
  869.                                     level = LEV_NONE;
  870.                                     FPutC(destf, (LONG)INTRODUCER_1);
  871.                                     MFPutC(destf, (LONG)*s, nolines);
  872.                                 }
  873.                                 break;
  874.                         
  875.                             case LEV_2 :
  876.                                 if( *s == TERMINATOR_1 )
  877.                                     level = LEV_3;
  878.                                 else
  879.                                     AddC2Cmd(cmd, *s);
  880.                                 break;
  881.                             
  882.                             case LEV_3 :
  883.                                 if( *s == TERMINATOR_2 )
  884.                                 {
  885.                                     level = LEV_NONE;
  886.                                     HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
  887.                                 } else
  888.                                 {
  889.                                     level = LEV_2;
  890.                                     AddC2Cmd(cmd, TERMINATOR_1);
  891.                                     AddC2Cmd(cmd, *s);
  892.                                 }
  893.                                 break;
  894.                         }
  895.                     }
  896.                     /* Do insertion if cmd has something in it (ie non terminated cmd) */
  897.                     if( *cmd != '\0' )
  898.                     {
  899.                         HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
  900.                         MFPutC(destf, '\n', nolines);
  901.                     }
  902.                     FreeVec(cmd);
  903.                 }
  904.             }                
  905.             FreeVec(buffer);
  906.         }
  907.         Close(sourcef);
  908.     } else
  909.         PrintFault(IoErr(), source);
  910. }
  911.  
  912.  
  913. /*************************************************************************
  914.  * main() - Ehhh... It's kinda ehhh...
  915.  */
  916.  
  917. int main( VOID )
  918. {
  919.     LONG rc = 10;
  920.     if( (((struct Library *)DOSBase)->lib_Version > 35) &&
  921.         (((struct Library *)SysBase)->lib_Version > 35) )
  922.     {
  923.         struct Vars *vars;
  924.         
  925.         /* Allocate var structure */
  926.         if( vars = AllocVec(sizeof(struct Vars), MEMF_CLEAR) )
  927.         {
  928.             struct RDArgs *rdargs;
  929.             #define TEMPLATE "SOURCE/A,DESTINATION,BUFFER/K/N,QUIET/S"
  930.             #define OPT_SOURCE 0
  931.             #define OPT_DEST 1
  932.             #define OPT_BUFFER 2
  933.             #define OPT_QUIET 3
  934.             #define OPT_MAX 4
  935.             #define DEF_BUFFER 4096
  936.             STRPTR args[OPT_MAX] = {0, 0, 0, 0};
  937.             #define ARG_SOURCE args[OPT_SOURCE]
  938.             STRPTR  ARG_DEST;
  939.             #define ARG_QUIET (BOOL)args[OPT_QUIET]
  940.         
  941.             /* Open Locale */
  942.             if( vars->v_LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library", 38) )
  943.                 vars->v_Locale = OpenLocale(NULL);
  944.             else
  945.                 vars->v_Locale = NULL;
  946.             LocaleBase = vars->v_LocaleBase;
  947.         
  948.             /* Parse arguments */
  949.             if (rdargs = ReadArgs(TEMPLATE, (LONG *)&args, NULL))
  950.             {
  951.                 BPTR srcl;
  952.                 
  953.                 ARG_DEST = args[OPT_DEST];
  954.                 
  955.                 if( args[OPT_BUFFER] )
  956.                     vars->v_BufSize = ((*((LONG *)args[OPT_BUFFER]) >= 208) ?
  957.                                          *((LONG *)args[OPT_BUFFER]) :
  958.                                          DEF_BUFFER);
  959.                 else
  960.                     vars->v_BufSize = DEF_BUFFER;
  961.                 
  962.                 /* Lock source */
  963.                 if( srcl = Lock(ARG_SOURCE, ACCESS_READ) )
  964.                 {
  965.                     BOOL makefilename = FALSE;
  966.                     BOOL destok = TRUE;
  967.                     
  968.                     if( ARG_DEST )
  969.                     {
  970.                         BPTR destl;
  971.                     
  972.                         /* Try to lock dest */
  973.                         if( destl = Lock(ARG_DEST, ACCESS_READ) )
  974.                         {
  975.                             /* Same file? */
  976.                             if( SameLock(srcl, destl) == LOCK_SAME )
  977.                             {
  978.                                 destok = FALSE;
  979.                                 SetIoErr(ERROR_OBJECT_EXISTS);
  980.                             }
  981.                             UnLock(destl);
  982.                         }
  983.                     } else
  984.                         makefilename = TRUE;
  985.                     
  986.                     if( makefilename )
  987.                     {
  988.                         /* Use a temp file */
  989.                         
  990.                         if( ARG_DEST = AllocVec(14, 0) )
  991.                         {
  992.                             strcpy(ARG_DEST, TMP_TEMP);
  993.                             mktemp(ARG_DEST);
  994.                             if( *ARG_DEST != 0 )
  995.                                 destok = TRUE;
  996.                         }
  997.                     }
  998.                     
  999.                     if( destok )
  1000.                     {
  1001.                         BPTR destf;
  1002.                         if( destf = Open(ARG_DEST, MODE_NEWFILE) )
  1003.                         {
  1004.                             /* Change buffer */
  1005.                             SetVBuf(destf, NULL, vars->v_BufSize, BUF_FULL);
  1006.                             
  1007.                             RepMarkers(vars, ARG_SOURCE, destf, FALSE);
  1008.                             Close(destf);
  1009.                             if( !ARG_QUIET )
  1010.                             {
  1011.                                 if( vars->v_Tags_p )
  1012.                                     Printf("%ld tags processed\n", vars->v_Tags_p);
  1013.                                 if( vars->v_Tags_e )
  1014.                                     Printf("%ld tags escaped\n", vars->v_Tags_e);
  1015.                                 if( vars->v_Tags_i )
  1016.                                     Printf("%ld invalid tags\n", vars->v_Tags_i);
  1017.                             }
  1018.                             rc = 0;
  1019.                         }
  1020.                     }
  1021.                     
  1022.                     UnLock(srcl);
  1023.                     
  1024.                     if( makefilename )
  1025.                     {
  1026.                         if( rc == 0)
  1027.                         {
  1028.                             BPTR src;
  1029.                             
  1030.                             /* Copy ARG_DEST to ARG_SOURCE */
  1031.                             
  1032.                             if( src    = Open(ARG_DEST, MODE_OLDFILE) )
  1033.                             {
  1034.                                 BPTR dest;
  1035.                                 
  1036.                                 if( dest = Open(ARG_SOURCE, MODE_NEWFILE) )
  1037.                                 {
  1038.                                     LONG ch;
  1039.                                     
  1040.                                     for( ch = FGetC(src); ch != -1; ch = FGetC(src) )
  1041.                                         FPutC(dest, ch);
  1042.                                     
  1043.                                     Close(dest);
  1044.                                 }
  1045.                                 Close(src);
  1046.                             }
  1047.                         }
  1048.                         
  1049.                         /* Delete the temp file */
  1050.                         DeleteFile(ARG_DEST);
  1051.                         
  1052.                         /* Free name buffer */
  1053.                         FreeVec(ARG_DEST);
  1054.                     }
  1055.  
  1056.                 }
  1057.                 FreeArgs(rdargs);
  1058.             }
  1059.         
  1060.             if( vars->v_Locale )
  1061.                 CloseLocale(vars->v_Locale);
  1062.                 
  1063.             if( vars->v_LocaleBase )
  1064.                 CloseLibrary((struct Library *)vars->v_LocaleBase);
  1065.             
  1066.             FreeVec(vars);
  1067.         }
  1068.     }
  1069.     if( rc )
  1070.         PrintFault(IoErr(), "Umentiler");
  1071.     return( rc );
  1072. }
  1073.